/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2020 @ ShenZhen ,China
*******************************************************************************/
#include "LocalMsgQueue.h"
#include "Tracer.h"
#include "Thread.h"

#define MAX_MESSAGES    200     /* 最大允许的消息条数 */

namespace libemb{
LocalMsgQueue::LocalMsgQueue()
{
    m_msgVector.clear();
}

LocalMsgQueue::~LocalMsgQueue()
{
    m_msgVector.clear(); 
}

/**
 *  \brief  发送消息
 *  \param  msg 消息体
 *  \return 成功返回STATUS_OK,失败返回STATUS_ERROR
 *  \note   none
 */
int LocalMsgQueue::sendMsg(QueueMsg_S& msg)
{
    if (msg.m_msgType<=0)
    {
        TRACE_ERR_CLASS("msg type must be greater than zero!\n");
        return STATUS_ERROR;
    }
    if (msg.m_dataLen>=MSG_SIZE_MAX)
    {
        TRACE_ERR_CLASS("msg data len must be less than %d!\n",MSG_SIZE_MAX);
        return STATUS_ERROR;
    }
    AutoLock lock(&m_mqLock);
    if (m_msgVector.size() > MAX_MESSAGES)
    {
        m_msgVector.clear();
        TRACE_ERR_CLASS("mqueue is full of %d messages, clear now!\n",MAX_MESSAGES);
        return STATUS_ERROR;
    } 
    else 
    {
        m_msgVector.push_back(msg);
    }
    return STATUS_OK;
}

/**
 *  \brief  接收消息
 *  \param  msg 消息体
 *  \param  msgType 消息类型
 *  \return 成功返回STATUS_OK,失败返回STATUS_ERROR
 *  \note   none
 */
int LocalMsgQueue::recvMsg(QueueMsg_S& msg, int msgType)
{
    Thread::msleep(10);
    AutoLock lock(&m_mqLock);
    if (m_msgVector.size()>0) 
    {
        vector<QueueMsg_S>::iterator iter;
        for (iter=m_msgVector.begin(); iter!=m_msgVector.end(); iter++) 
        {
            if (iter->m_msgType==msgType) 
            {
                msg = *iter;
                m_msgVector.erase(iter);
                break;
            }
        }
    }
    else
    {
        return STATUS_ERROR;
    }
	return STATUS_OK;
}

/**
 *  \brief  清空消息
 *  \param  msgType 消息体
 *  \return 成功返回STATUS_OK,失败返回STATUS_ERROR
 *  \note   msgType=0 清空队列中所有的消息
 *          msgType>0 清空队列中类型值为msgType的消息
 *          msgType<0 清空队列中类型值小于或等于|msgType|的消息
 */
int LocalMsgQueue::clearMsg(int msgType)
{
    QueueMsg_S msg;
    while(recvMsg(msg, msgType)==STATUS_OK)
    {
        continue;
    }
    return STATUS_OK;
}

LocalMsgQueueFactory::LocalMsgQueueFactory()
{
}
LocalMsgQueueFactory::~LocalMsgQueueFactory()
{
    std::map<int, LocalMsgQueue*>::iterator iter;
    for (iter=m_msgQueueMap.begin(); iter!=m_msgQueueMap.end(); iter++) 
    {
        DEL_OBJ(iter->second);
    }
    m_msgQueueMap.clear();
}
/**
 *  \brief  从消息队列工厂取得消息队列
 *  \param  key 消息队列的key
 *  \return MsgQueue* 成功返回消息队列,失败返回NULL
 *  \note   none
 */
LocalMsgQueue* LocalMsgQueueFactory::getMsgQueue(int key)
{
    AutoLock lock(&m_lock);
	std::map<int, LocalMsgQueue*>::iterator iter = m_msgQueueMap.find(key);
	if (iter!=m_msgQueueMap.end())
	{
		return iter->second;
	}
    else 
    {
        LocalMsgQueue* pMsg = NEW_OBJ LocalMsgQueue();
		if (pMsg==NULL)
		{
			return NULL;
		}
        m_msgQueueMap.insert(std::make_pair(key, pMsg));
		return pMsg;
	}
}
}